package cn.hg.solon.youcan.system.provider;

import cn.hg.solon.youcan.common.constant.AppConstants;
import cn.hg.solon.youcan.common.exception.ServiceException;
import cn.hg.solon.youcan.flex.util.QueryWrapperUtil;
import cn.hg.solon.youcan.system.entity.Dict;
import cn.hg.solon.youcan.system.entity.SysDict;
import cn.hg.solon.youcan.system.mapper.SysDictMapper;
import cn.hg.solon.youcan.system.service.DictItemService;
import cn.hg.solon.youcan.system.service.DictService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.convert.ConvertUtil;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.text.CharSequenceUtil;
import org.dromara.hutool.core.text.StrValidator;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.db.PageResult;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Tran;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import static cn.hg.solon.youcan.system.entity.table.SysDictItemTableDef.SYS_DICT_ITEM;
import static cn.hg.solon.youcan.system.entity.table.SysDictTableDef.SYS_DICT;

/**
 * @author 胡高
 */
@Component
public class SysDictProvider extends ServiceImpl<SysDictMapper, SysDict> implements DictService {

    @Inject
    private DictItemService dictItemService;

    @Override
    public boolean checkUnique(Dict bean) {
        // 查找已存在记录
        QueryWrapper query = QueryWrapper.create()
                .where(SYS_DICT.TYPE.eq(bean.getType())
                        .and(SYS_DICT.ID.ne(bean.getId()))
                );

        return ObjUtil.isNull(this.getOne(query));
    }

    @Tran
    @Override
    public boolean delete(List<Integer> idList) {
        for (Serializable id : idList) {
            SysDict dict = this.getMapper().selectOneById(id);

            if (ObjUtil.isNotNull(dict)) {
                if (this.getMapper().selectCountByCondition(SYS_DICT_ITEM.TYPE.eq(dict.getType())) > 0) {
                    throw new ServiceException(AppConstants.RETURN_CODE_VALUE_FAIL, "[" + dict.getName() + "] 中存在子项，不允许删除！");
                }
            }
        }

        return this.getMapper().deleteBatchByIds(idList) > 0;
    }

    @Override
    public SysDict get(Integer id) {
        return this.getMapper().selectOneById(id);
    }

    @Override
    public SysDict getByType(String type) {
        QueryWrapper query = QueryWrapper.create().where(SYS_DICT.TYPE.eq(type));
        return this.getOne(query);
    }

    @Tran
    @Override
    public boolean insert(Dict bean) {
        if (!this.checkUnique(bean)) {
            throw new ServiceException("字典名称已经存在，请更换其它值！");
        }

        SysDict cloneBean = BeanUtil.copyProperties(bean, SysDict.class);

        return this.getMapper().insert(cloneBean) > 0;
    }

    @Override
    public List<SysDict> listByStatus(String status) {
        return this.getMapper().selectListByCondition(SYS_DICT.STATUS.eq(status));
    }

    @Override
    public List<SysDict> listBy(Map<String, Object> paraMap) {
        if (ObjUtil.isNull(paraMap)) {
            paraMap = MapUtil.empty();
        }
        return this.getMapper().selectListByQuery(buildQuery(paraMap));
    }

    private QueryWrapper buildQuery(Map<String, Object> paraMap) {
        String type = (String) paraMap.get("type");
        String status = (String) paraMap.get("status");
        String word = (String) paraMap.get("word");

        QueryWrapper query = QueryWrapper.create()
                .where(SYS_DICT.TYPE.eq(type).when(StrValidator.isNotBlank(type))
                        .and(SYS_DICT.STATUS.eq(status).when(StrValidator.isNotBlank(status)))
                        .and(SYS_DICT.NAME.like(word).when(StrValidator.isNotBlank(word))
                                .or(SYS_DICT.TYPE.like(word).when(StrValidator.isNotBlank(word)))
                        )
                );
        return query;
    }

    @Override
    @Tran
    public PageResult<SysDict> pageBy(org.dromara.hutool.db.Page page, Map<String, Object> paraMap) {
        Page<SysDict> pageList = this.getMapper().paginate(Page.of(page.getPageNumber(), page.getPageSize()),
                QueryWrapperUtil.applyOrderBy(buildQuery(paraMap), page));

        PageResult<SysDict> result = new PageResult<>();
        result.addAll(pageList.getRecords());
        result.setTotal(ConvertUtil.toInt(pageList.getTotalRow()));

        return result;
    }

    @Tran
    @Override
    public boolean update(Dict bean) {
        if (!this.checkUnique(bean)) {
            throw new ServiceException("字典名称已经存在，请更换其它值！");
        }

        SysDict cloneBean = BeanUtil.copyProperties(bean, SysDict.class);

        /*
         * 更新子项的type名
         */
        this.updateItemType(cloneBean);

        return this.getMapper().update(cloneBean) > 0;
    }

    private void updateItemType(SysDict bean) {
        /*
         * 获取当前存在的字典记录
         */
        SysDict exist = this.get(bean.getId());

        /*
         * 如果类型名不变
         */
        if (ObjUtil.isNull(exist) || CharSequenceUtil.equals(bean.getType(), exist.getType())) {
            return;
        }

        /*
         * 如果修改了类型，则需要同步修改子项的类型名
         */
        this.dictItemService.updateTypeName(exist.getType(), bean.getType());
    }
}
